import {getUrlParams} from 'M/Utils';
import {Linking, Platform} from 'react-native';
import {UpViewEvent} from 'M/UI/Components/UpViewParent';
import {inLinkMap} from 'WE/Services';
import {ToastManager} from 'M/UI/Libraries/Toast';
import DeviceInfo from 'M/Utils/DeviceInfo';

type InLinkParamsType = {
  params: object;
  type: string;
};

const ios = Platform.OS.toLowerCase() === 'ios';

class GlobalService {
  private _upViewEvent = {} as UpViewEvent;
  private toast = ToastManager;
  private navigation = {} as any;
  private ios = ios;
  private android = Platform.OS.toLowerCase() === 'android';
  private osVersion = parseInt(`${Platform.Version || 0}`);
  private device = new DeviceInfo(this.ios);

  constructor() {}

  getDeviceInfo() {
    return this.device.getDeviceInfo();
  }

  getOsVersion() {
    return this.osVersion;
  }

  isIOS() {
    return this.ios;
  }

  isAndroid() {
    return this.android;
  }

  addLinkingEventListener(callback?: Function) {
    Linking.getInitialURL()
      .then(url => globalService.getOnfulfilled(url, callback))
      .finally(() => console.log('Linking.getInitialURL().done'));
    return Linking.addEventListener('url', ({url}) =>
      globalService.getOnfulfilled(url, callback),
    );
  }

  private getOnfulfilled(url: any, callback: Function | undefined) {
    return callback ? callback(url) : this.initialURL(url);
  }

  initialURL(url: any) {
    if (url) {
      try {
        const {type, ...params} = getUrlParams(url);
        globalService.doInLink({params, type});
      } catch (e) {
        console.log(e);
      }
    }
  }

  getNav() {
    return this.navigation;
  }

  setNav(navigation: any) {
    this.navigation = navigation;
  }

  getToast() {
    return this.toast;
  }

  throwError(
    bool: boolean,
    errorCode: {message: string; code: string},
    mappings?: {[key: string]: any},
  ) {
    if (bool) {
      let {message} = errorCode;
      for (const key in mappings) {
        message = message.replace(`{${key}}`, mappings[key]);
      }
      errorCode.message = message;
      throw {...errorCode, message};
    }
  }

  setUpView(value: UpViewEvent) {
    this._upViewEvent = value;
  }

  getUpView() {
    return this._upViewEvent;
  }

  doInLink({params, type}: InLinkParamsType) {
    let map = inLinkMap as {[key: string]: any};
    if (map && map[type]) {
      map[type](params);
    }
  }
}

const globalService = new GlobalService();
export default globalService;
